fix(toolpath-convo): consult git HEAD for Write-tool before-state#48
Merged
Conversation
`file_write_diff` now takes a `before_state: Option<&str>` parameter.
For the `Write { content }` shape, when `Some` it becomes the diff
pre-image — so overwriting an existing file shows real `-`/`+` lines
instead of an addition-only hunk. `None` preserves the old behaviour
(diff against `""`), correct for new files.
`toolpath-claude`'s Claude-JSONL deriver wires a best-effort git
lookup for Write invocations: shells out to `git show HEAD:<relpath>`
using the turn's `cwd` (with fallback to the conversation's project
path). Silently falls back to the additions-only diff when the
project isn't a git repo, the file isn't tracked at HEAD, or `git`
isn't on PATH.
Edit / MultiEdit are unchanged — they already carry their own
`old_string`/`new_string`.
Closes #35
|
🔍 Preview deployed: https://df5cbd6d.toolpath.pages.dev |
eliothedeman
commented
Apr 22, 2026
Collaborator
Author
eliothedeman
left a comment
There was a problem hiding this comment.
Summary
Cleanly fixes #35 by threading before_state: Option<&str> through file_write_diff / file_write_change and wiring a best-effort git show HEAD:<rel> lookup at the Claude call site. Public API break on toolpath-convo is properly versioned (0.7.0) and all four required locations are updated.
Notes
crates/toolpath-claude/src/derive.rs:22-44—git_head_contentusesCommand::new("git").arg(...)with-C, so no shell and no injection surface.format!("HEAD:{rel_str}")is passed as a single argv element. Safe.crates/toolpath-claude/src/derive.rs:51-60—resolve_local_dirprecedence (entry cwd > config > convo) is the right call per-turn;file://stripping is handled once at resolve time.crates/toolpath-claude/src/derive.rs:533-553— only Writes consult git; Edit/MultiEdit correctly skip the lookup..and_thenchain means any failure (no repo / untracked / git missing) falls through to additions-only.crates/toolpath-convo/src/derive.rs:175-179— shared deriver passesNonewith an explanatory comment about providers with local checkout access overriding. Clean boundary.- Tests: both paths covered — unit tests for
Some/None/Edit-ignored, plus two realtempfile+git initintegration tests asserting-old-content/ no removal lines. Matches the rubric. - Versioning:
crates/toolpath-convo/Cargo.toml, workspaceCargo.toml,site/_data/crates.json,CHANGELOG.mdall updated to 0.7.0. Cargo.lock reflects it. CI green. - No scope creep; no feature flags or backcompat shims.
Verdict
Approve (posted as comment — GitHub blocks self-approval). Surgical fix, correct API shape, safe subprocess call, symmetric tests, versioning complete.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
toolpath_convo::file_write_diffgains abefore_state: Option<&str>parameter. For theWrite { content }shape,Some(prior)becomes the diff pre-image;Nonepreserves the old behaviour (diff against""). Edit/MultiEdit paths are unchanged — they already carry their ownold_string/new_string.toolpath-claude's Claude-JSONL deriver wires a best-effort git-HEAD lookup forWriteinvocations: shells out togit show HEAD:<relpath>using the turn'scwd(falls back to the conversation's project path). Silently returnsNonewhen the project isn't a git repo, the file isn't tracked at HEAD, orgitisn't onPATH— the deriver then produces the existing additions-only diff.toolpath-convobumped to 0.7.0 (public API break).Closes #35
Test plan
file_write_diffwithSome(before)shows-lines for replaced contentfile_write_diffwithNoneis addition-only (existing behaviour preserved)before_stateignored forEditshaperesolve_local_dirprecedence (entry cwd > config > conversation),file://prefix strippinggit init+ commit + ClaudeWritetool → derivedrawdiff has-old-contentand+new-contentWrite→ additions-only fallback (no-lines)cargo test --workspace(1209 passed, 0 failed)cargo clippy --workspace -- -D warningsclean